﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Web.Http;

//[assembly: Microsoft.Owin.OwinStartup(typeof(Cypher.Core.Managers.CypherManager), "UseApiDocumentation")]

namespace Owin
{
	public static class CypherAppBuilderExtentions
	{
		public static IAppBuilder UseApiDocumentation(this IAppBuilder builder, System.Web.Http.HttpConfiguration configuration)		
		{
			var documentationSection = Cypher.Core.Configuration.ConfigurationManager.Get();

			var providerType = Type.GetType(documentationSection.ProviderType);
			if (providerType == null)
				providerType = typeof(Cypher.Core.Default.DefaultDocumentationProvider);

			if (providerType != null && typeof(System.Web.Http.Description.IDocumentationProvider).IsAssignableFrom(providerType))
			{
				var instance = Activator.CreateInstance(providerType, documentationSection.Documentationfile);

				configuration.Services.Replace(typeof(System.Web.Http.Description.IDocumentationProvider), instance);

				ReplaceTypeResolver(configuration);

				// Register the route according to the settings in the configuration
				RegisterRoutes(documentationSection.Services, configuration);
			}

			// patch for removing the default controller suffix convention!
			var suffix = typeof(System.Web.Http.Dispatcher.DefaultHttpControllerSelector).GetField("ControllerSuffix", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
			if (suffix != null) suffix.SetValue(null, string.Empty);			

			return builder;
		}

		private static void ReplaceTypeResolver(System.Web.Http.HttpConfiguration configuration)
		{
			var resolver = new Cypher.Core.ServiceTypeResolver(true);
			configuration.Services.Replace(typeof(System.Web.Http.Dispatcher.IHttpControllerTypeResolver), resolver);
		}

		private static void RegisterRoutes(Cypher.Core.Configuration.ServiceElementCollection serviceElementCollection, System.Web.Http.HttpConfiguration configuration)
		{
			//TODO: Check if service.Name as route id, is unique
			foreach (Cypher.Core.Configuration.ServiceElement serviceElement in serviceElementCollection)
			{
				var type = Type.GetType(serviceElement.Type);
				if (type == null)
					continue;

				configuration.Routes.MapHttpRoute(
					name: serviceElement.Name,
					routeTemplate: serviceElement.Uri.OriginalString,
					defaults: new { controller = type.Name, placeholder = string.Empty }
				);
			}
		}
	}
}